import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

public class CASDemo {
    // AtomicStampedReference 注意，如果泛型是一个包装类(如：Integer)，注意对象的引用问题
    // 正常在业务操作，这里面比较的都是一个个对象
    static AtomicStampedReference<Integer> atomicStampedReference = new
            //第一个参数是值，第二个参数是stamp
            AtomicStampedReference<>(1,1);
    public static void main(String[] args) {
        new Thread(()->{
            int stamp = atomicStampedReference.getStamp(); // 获得版本号
            System.out.println("A线程第一次输出的版本号=>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //这里进行compareAndSet，前两个参数大家都知道，主要是后两个参数是，获取当前的Stamp，以及当前的Stamp+1
            //回想一下乐观锁一下子就明白了，就是每次你操作过了，就更新一下stamp，表示操作过一次了
            atomicStampedReference.compareAndSet(1, 2,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1);

            //输出版本
            System.out.println("A线程第二次输出的版本号=>"+atomicStampedReference.getStamp());

            //这里进行compareAndSet
            System.out.println(atomicStampedReference.compareAndSet(2, 1,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1));

            //输出版本
            System.out.println("A线程第三次输出的版本号=>"+atomicStampedReference.getStamp());

        },"a").start();
// 乐观锁的原理相同！
        new Thread(()->{

            int stamp = atomicStampedReference.getStamp(); // 获得版本号
            System.out.println("B线程第一次输出的版本号=>"+stamp);

            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //这里进行compareAndSet
            System.out.println(atomicStampedReference.compareAndSet(1, 6,
                    stamp, stamp + 1));

            //输出版本
            System.out.println("B线程第二次输出的版本号=>"+atomicStampedReference.getStamp());
        },"b").start();
    }

}